import java.util.*;
import java.awt.Point;

/**
 * @author Marcel Heinrichs
 *
 */
public class Robot implements Runnable {
	// Attribute
	public static final int NORTH = 0;
	public static final int EAST = 1;
	public static final int SOUTH = 2;
	public static final int WEST = 3;
	private Point currentPos;
	private int direction;
	// Der Boolean-Wert ist true, wenn die Position versperrt ist
	private Hashtable<Point, Boolean> mapping = new Hashtable<Point, Boolean>();
	private Map map;
	private boolean exit = false;
	// Methoden
	public Robot(Point startPos, int direction, Map map) throws Exception {
		this.currentPos = startPos;
		this.mapping.put(startPos, false);
		this.direction = direction;
		this.map = map;
		if(map.isBlocked(startPos))
			throw new Exception("Roboter steht in einem Hindernis");
	}
	private boolean moveForward() {
		Point bufferPos;
		switch(direction) {
			case 0:
				// Prüfe ob der Weg nach Norden frei ist
				bufferPos = new Point(this.currentPos.x, this.currentPos.y + 1);
				if(this.map.isBlocked(bufferPos)) 
					this.mapping.put(bufferPos, true);
				else {
					this.mapping.put(bufferPos, false);
					this.currentPos = bufferPos;
					return true;
				}
				break;
			case 1:
				// Prüfe ob der Weg nach Osten frei ist
				bufferPos = new Point(this.currentPos.x + 1, this.currentPos.y);
				if(this.map.isBlocked(bufferPos)) 
					this.mapping.put(bufferPos, true);
				else {
					this.mapping.put(bufferPos, false);
					this.currentPos = bufferPos;
					return true;
				}
				break;
			case 2:
				// Prüfe ob der Weg nach Süden frei ist
				bufferPos = new Point(this.currentPos.x, this.currentPos.y - 1);
				if(this.map.isBlocked(bufferPos)) 
					this.mapping.put(bufferPos, true);
				else {
					this.mapping.put(bufferPos, false);
					this.currentPos = bufferPos;
					return true;
				}
				break;
			case 3:
				// Prüfe ob der Weg nach West frei ist
				bufferPos = new Point(this.currentPos.x - 1, this.currentPos.y);
				if(this.map.isBlocked(bufferPos)) 
					this.mapping.put(bufferPos, true);
				else {
					this.mapping.put(bufferPos, false);
					this.currentPos = bufferPos;
					return true;
				}
				break;
		}
		return false;
	}
	private void turnLeft() {
		switch(this.direction) {
			case NORTH:
				this.direction = WEST;
				System.out.println("Roboter dreht sich nach Links richtung Westen");
				break;
			case WEST:
				this.direction = SOUTH;
				System.out.println("Roboter dreht sich nach Links richtung Süden");
				break;
			case SOUTH:
				this.direction = EAST;
				System.out.println("Roboter dreht sich nach Links richtung Osten");
				break;
			case EAST:
				this.direction = NORTH;
				System.out.println("Roboter dreht sich nach Links richtung Norden");
				break;
		}
	}
	private void turnRight() {
		switch(this.direction) {
			case NORTH:
				this.direction = EAST;
				System.out.println("Roboter dreht sich nach Rechts richtung Osten");
				break;
			case EAST:
				this.direction = SOUTH;
				System.out.println("Roboter dreht sich nach Rechts richtung Süden");
				break;
			case SOUTH:
				this.direction = WEST;
				System.out.println("Roboter dreht sich nach Rechts richtung Westen");
				break;
			case WEST:
				this.direction = NORTH;
				System.out.println("Roboter dreht sich nach Rechts richtung Norden");
				break;
		}
	}
	public void run() {
		int moves = 0;
		while(!exit) {
			moves++;
			try {
				// Warte eine halbe Sekunde bei jedem Durchgang
				Thread.sleep(50);
			} catch(InterruptedException e) {}
			
			// TODO Smart Pathfinding
			
			// Wenn der Weg versperrt ist suche nach einer Alternative
			if(!moveForward()) {
				System.out.println("Weg ist versperrt @ " + currentPos);
				Random r = new Random();
				// Wenn true, drehe nach links
				if(r.nextBoolean()) 
					turnLeft();
				// Wenn false, drehe nach rechts
				else 
					turnRight();
			}
			else {
				Random r = new Random();
				if(r.nextFloat() > 0.9)
					if(r.nextBoolean())
						turnLeft();
					else
						turnRight();
			}
			System.out.println("Roboter bewegt sich auf " + this.currentPos);
			if((this.currentPos.x == 0 || this.currentPos.x == map.getSizeX()) 
					|| (this.currentPos.y == 0 || this.currentPos.y == map.getSizeY()))
				this.exit = true;
		}
		System.out.println("Der Roboter hat den Ausgang nach " + moves + " Zügen gefunden!");
	}
}
